#include "level.h"

#include <iostream>
#include <fstream>
#include <iterator>
#include <string>

#include <SFML/Graphics/RenderTarget.hpp>

#include "player.h"
#include "collision.h"

Level *Level::loadFile(const std::string &filename)
{
    std::ifstream file(filename.c_str());

    if ( !file ) {
        std::cerr << "Unable to open " << filename << " for reading.";
        return 0;
    }

    // Retrieve header data.
    std::string header;

    if ( !(std::getline(file, header) && header == "P2") ) {
        std::cerr << "Incorrect header: got " << header;
        return 0;
    }

    int Width, Height, types;
    file >> Width >> Height >> types;

    if ( !(Width == Width && Height == Height) )
        return 0;

    // Read all block data.
    std::vector<int> blocks;

    std::copy(std::istream_iterator<int>(file), std::istream_iterator<int>(), std::back_inserter(blocks));

    // Create the level.
    Level *lvl = new Level;
    for (int x = 0; x < Width; ++x)
        for (int y = 0; y < Height; ++y)
            if (blocks[x + y*Width] != Block::Void)
                lvl->setBlock(x, y, Block::Type(blocks[x + y*Width]));

    return lvl;
}

bool Level::saveFile(const Level &lvl, const std::string &filename)
{
    std::ofstream file(filename.c_str());
    if ( !file ) {
        std::cerr << "Unable to open " << filename << " for writing.";
        return false;
    }

    // Header.
    file    << "P2\n"
            << Width << ' ' << Height << '\n'
            << "5\n";

    // Write data.
    for (int y = 0; y < Height; ++y) {
        for (int x = 0; x < Width; ++x) {
            Block *block = lvl.blockAt(x, y);
            file << (block ? block->type() : Block::Void) << ' ';
        }
        file << '\n';
    }

    return true;
}

Level::Level(void) :
    sf::Drawable()
{
}

Level::~Level(void)
{
}

void Level::checkCollisions(Player &player)
{
    sf::Vector2i corner(int(player.GetPosition().x / Block::Width),
                            int((player.GetPosition().y + Player::Height) / Block::Height));

    // Bottom left.
    Block *block = blockAt(corner);
	
	if (block && Collision::BoundingBoxTest(*block, player))
	{
		block->action(player);
        return;
	}
	corner.x += Player::Width / Block::Width;
	block = blockAt(corner.x, corner.y);
	if (block && Collision::BoundingBoxTest(*block, player))
	{
		block->action(player);
	}
    /*if (block) {
        block->action(player);
        return;
    }*/

    // Bottom right.
    /*corner.x += Player::Width / Block::Width;
    block = blockAt(corner.x, corner.y);

    if (block)
        block->action(player);*/
}

void Level::Render(sf::RenderTarget &target) const
{
    for (std::map<int, Block *>::const_iterator block = m_blocks.begin();
                                            block != m_blocks.end(); ++block)
        target.Draw(*(block->second));
}
